﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Win32;

namespace Aribaccio.Copyright
{
    /// <summary>
    /// 注册版权期限基类
    /// </summary>
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class RegisterCopyBase
    {
        /// <summary>
        /// 注册表键实例
        /// </summary>
        protected RegistryKey RegistKey { get; set; }
        /// <summary>
        /// 注册表访问规则实例
        /// </summary>
        protected RegistrySecurity RegistSecurity { get; set; }
        /// <summary>
        /// 注册项键值-注册默认开始时间【当前时间】
        /// </summary>
        protected DateTime RegisterTimeSatrt { get; set; }
        /// <summary>
        /// 注册项键值-注册默认版权信息项对象
        /// </summary>
        protected IRegisterCopyPara RegisterPara { get; set; }

        /// <summary>
        /// 注册项路径
        /// </summary>
        public string RegistryKeyPath { get; protected set; }
        /// <summary>
        /// 注册项名称
        /// </summary>
        public string RegistryKeyName { get; protected set; }
        /// <summary>
        /// 注册项完整路径名称
        /// </summary>
        public string RegistryKeyPathName => this.RegistryKeyPath + "\\" + this.RegistryKeyName;
        /// <summary>
        /// 注册项键名称-序列号+结束/终止时间
        /// </summary>
        public string RegistrySubKeySerialNum { get; protected set; }
        /// <summary>
        /// 注册项键名称-起始时间
        /// </summary>
        public string RegistrySubKeyStart { get; protected set; }
        /// <summary>
        /// 注册项键名称-最后访问时间
        /// </summary>
        public string RegistrySubKeyLast { get; protected set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public RegisterCopyBase()
        {
            this.RegistryKeyPath = "SOFTWARE";
            this.RegistryKeyName = "SecretSerial";
            this.RegistrySubKeySerialNum = "SerialNumber";
            this.RegistrySubKeyStart = "SerialStartTime";
            this.RegistrySubKeyLast = "SerialLastTime";
            this.RegisterTimeSatrt = Convert.ToDateTime(DateTime.Now.ToShortDateString());
            this.RegisterPara = new RegisterCopyPara();
            this.RegistKey = Registry.LocalMachine;
            //创建RegistrySecurity对象并设置访问规则
            this.RegistSecurity = new RegistrySecurity();
            // 允许修改访问规则
            this.RegistSecurity.SetAccessRuleProtection(false, false);
            // 添加访问规则
            this.RegistSecurity.AddAccessRule(new RegistryAccessRule("Everyone", RegistryRights.FullControl, AccessControlType.Allow));
        }

        /// <summary>
        /// 检查注册表项是否存在
        /// </summary>
        /// <param name="argKeyName"></param>
        /// <returns></returns>
        protected bool ExistRegistryKey(string argKeyName)
        {
            if (string.IsNullOrWhiteSpace(argKeyName)) { return false; }
            bool bResultFlag = false;
            try
            {
                RegistryKey registSubKey = RegistKey.OpenSubKey(RegistryKeyPath, true);
                if (registSubKey != null)
                {
                    //获取子项下的所有注册表项
                    string[] SubKeyNames = registSubKey.GetSubKeyNames();
                    foreach (string KeyName in SubKeyNames)
                    {
                        if (KeyName == argKeyName)
                        {
                            bResultFlag = true;
                            break;
                        }
                    }
                    registSubKey.Close();
                }
            }
            catch (Exception) { bResultFlag = false; }
            finally { RegistKey.Close(); }
            return bResultFlag;
        }

        /// <summary>
        /// 检查注册表项键值是否存在
        /// </summary>
        /// <param name="argKeyName"></param>
        /// <returns></returns>
        protected bool ExistRegistryKeyValue(string argKeyName)
        {
            if (string.IsNullOrWhiteSpace(argKeyName)) { return false; }
            object? obj = this.ReadRegisterSubKeyValue(argKeyName);
            return obj != null;
        }

        /// <summary>
        /// 删除注册表中指定键值
        /// </summary>
        /// <param name="argKeyName"></param>
        /// <returns></returns>
        public bool DeleteRegisterSubKey(string argKeyName)
        {
            if (string.IsNullOrWhiteSpace(argKeyName)) { return false; }
            try
            {
                //该项必须已存在
                RegistryKey registSubKey = RegistKey.OpenSubKey(RegistryKeyPathName, true);
                if (registSubKey != null)
                {
                    registSubKey.DeleteValue(argKeyName);
                    registSubKey.Close();
                    return true;
                }
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 写入注册表项
        /// </summary>
        /// <returns></returns>
        protected bool WriteRegisterSubKey()
        {
            try
            {
                // 使用CreateSubKey方法创建子键，并指定访问权限
                this.RegistKey.CreateSubKey(RegistryKeyPathName, RegistryKeyPermissionCheck.Default, this.RegistSecurity);
                return true;
            }
            catch (Exception) { return false; }
        }

        /// <summary>
        /// 写入注册表项键值
        /// </summary>
        /// <param name="argKeyName"></param>
        /// <param name="argKeyValue"></param>
        /// <returns></returns>
        protected bool WriteRegisterSubKeyValue(string argKeyName, object argKeyValue)
        {
            if (string.IsNullOrWhiteSpace(argKeyName)) { return false; }
            if (argKeyValue == null || string.IsNullOrWhiteSpace(argKeyValue.ToString())) { return false; }
            bool bResultFlag = false;
            try
            {
                //该项必须已存在
                RegistryKey registSubKey = RegistKey.OpenSubKey(RegistryKeyPathName, true);
                if (registSubKey != null)
                {
                    //写入注册表项键值
                    registSubKey.SetValue(argKeyName, argKeyValue);
                    bResultFlag = true;
                    registSubKey.Close();
                }
            }
            catch (Exception) { bResultFlag = false; }
            finally { RegistKey.Close(); }
            return bResultFlag;
        }

        /// <summary>
        /// 读取注册表项键值
        /// </summary>
        /// <param name="argKeyName"></param>
        /// <returns></returns>
        protected object? ReadRegisterSubKeyValue(string argKeyName)
        {
            if (string.IsNullOrWhiteSpace(argKeyName)) { return null; }
            object objResultFlag = null;
            try
            {
                RegistryKey registSubKey = RegistKey.OpenSubKey(RegistryKeyPathName, true);
                if (registSubKey != null)
                {
                    objResultFlag = registSubKey.GetValue(argKeyName);
                    registSubKey.Close();
                }
            }
            catch (Exception) { objResultFlag = null; }
            finally { RegistKey.Close(); }
            return objResultFlag;
        }

        /// <summary>
        /// 读取系统所在硬盘的序列号
        /// </summary>
        /// <returns></returns>
        protected string ReadSystemDiskNo()
        {
            try
            {
                ManagementClass cimobject = new ManagementClass("Win32_PhysicalMedia");
                ManagementObjectCollection moc = cimobject.GetInstances();
                Dictionary<string, string> dict = new Dictionary<string, string>();
                foreach (ManagementObject mo in moc)
                {
                    string tag = mo.Properties["Tag"].Value.ToString()?.ToLower().Trim();
                    if (string.IsNullOrEmpty(tag)) continue;

                    string hdid = (string)mo.Properties["SerialNumber"].Value ?? string.Empty;
                    hdid = hdid.Trim();
                    dict.Add(tag, hdid);
                }
                cimobject = new ManagementClass("Win32_OperatingSystem");
                moc = cimobject.GetInstances();
                string currentSysRunDisk = string.Empty;
                foreach (ManagementObject mo in moc)
                {
                    string strName = mo.Properties["Name"].Value.ToString()?.ToLower().Trim();
                    if (string.IsNullOrEmpty(strName)) continue;
                    currentSysRunDisk = Regex.Match(strName, @"harddisk\d+").Value;
                }
                var results = dict.Where(x => Regex.IsMatch(x.Key, @"physicaldrive" + Regex.Match(currentSysRunDisk, @"\d+$").Value));
                return results.Any() ? results.ElementAt(0).Value.ToString() : "";
            }
            catch (Exception) { return ""; }
        }

        /// <summary>
        /// 读取本机CPUID
        /// </summary>
        /// <returns></returns>
        protected string ReadSystemCPUID()
        {
            string strCpuID = string.Empty;
            try
            {
                ManagementClass mc = new ManagementClass("Win32_Processor");
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    strCpuID = mo.Properties["ProcessorId"].Value.ToString();
                    break;
                }
            }
            catch (Exception) { strCpuID = string.Empty; }
            return strCpuID ?? string.Empty;
        }
    }
}
